package at.fhj.swd.pse.domain;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityNotFoundException;

import org.apache.commons.codec.binary.Hex;
import org.jboss.logging.Logger;

import at.fhj.swd.pse.data.UserDAO;
import at.fhj.swd.pse.entities.Activity;
import at.fhj.swd.pse.entities.EActivityType;
import at.fhj.swd.pse.entities.User;

/**
 * @author Florian Maderbacher
 **/

public class UserServiceImpl implements UserService, Serializable {
	private static final long serialVersionUID = 1L;

	private static final Logger m_logger = Logger.getLogger(UserServiceImpl.class);

	@Inject
	@Named("userDAOImpl")
	private UserDAO m_dao;

	@Inject
	private ActivityService as;

	@Override
	public User login(final String username, final String password) {
		String passwordHash = CalcHash(password);
		return this.m_dao.getByLogin(username, passwordHash);
	}

	@Override
	public User getUserProfileByUserId(final int userId) {
		m_logger.info("UserService - getUserProfileByUserId: " + userId);
		User userProfile = this.m_dao.get(userId);
		if (userProfile == null) {
			throw new EntityNotFoundException("Can't find User Profile for User-ID " + userId);
		}
		return userProfile;
	}

	private static String CalcHash(final String password) {
		String passwordHash = null;

		if (password != null) {
			MessageDigest cript;
			try {
				cript = MessageDigest.getInstance("SHA-1");
				cript.reset();
				cript.update(password.getBytes("utf8"));
				passwordHash = new String(Hex.encodeHex(cript.digest()));
			} catch (NoSuchAlgorithmException ex) {
				m_logger.error("SHA-1 hash not available.", ex);
			} catch (UnsupportedEncodingException ex) {
				m_logger.error("UTF8-Encoding not supportet.", ex);
			}
		}

		return passwordHash;
	}

	@Override
	public void updateUser(final User user) {
		m_logger.info("Update user: " + user.getUsername());
		this.m_dao.update(user);
	}

	@Override
	public void setUserDAO(final UserDAO userDao) {
		this.m_dao = userDao;
	}
	
	public void setAs(ActivityService as) {
		this.as = as;
	}

	@Override
	public void addFriend(final User user, final User friend) {
		Set<User> friends = user.getFriends();
		friends.add(friend);
		if (!friend.getFriends().contains(user)) {
			Set<User> friendfriends = friend.getFriends();
			friendfriends.add(user);
			friend.setFriends(friendfriends);
			this.m_dao.update(friend);
		}
		user.setFriends(friends);
		this.m_dao.update(user);

		Activity userActivity = new Activity();
		Activity friendActivity = new Activity();
		userActivity.setCreator(user);
		friendActivity.setCreator(friend);
		userActivity.setTimestamp(new Date());
		friendActivity.setTimestamp(new Date());
		userActivity.setText("is now friend with " + friend.getFirstName() + " " + friend.getLastName());
		friendActivity.setText("is now friend with " + user.getFirstName() + " " + user.getLastName());
		userActivity.setType(EActivityType.Global);
		friendActivity.setType(EActivityType.Global);
		this.as.createNewActivity(userActivity);
		this.as.createNewActivity(friendActivity);
	}

	@Override
	public List<User> getUsers() {
		return this.m_dao.getAll();
	}

	@Override
	public void removeFriend(final User user, final User friend) {
		Set<User> friends = user.getFriends();
		Set<User> friendfriends = friend.getFriends();
		friends.remove(friend);
		friendfriends.remove(user);
		friend.setFriends(friendfriends);
		user.setFriends(friends);
		this.m_dao.update(friend);
		this.m_dao.update(user);

		Activity userActivity = new Activity();
		Activity friendActivity = new Activity();
		userActivity.setCreator(user);
		friendActivity.setCreator(friend);
		userActivity.setTimestamp(new Date());
		friendActivity.setTimestamp(new Date());
		userActivity.setText("is no longer friend with " + friend.getFirstName() + " " + friend.getLastName());
		friendActivity.setText("is no longer friend with " + user.getFirstName() + " " + user.getLastName());
		userActivity.setType(EActivityType.Global);
		friendActivity.setType(EActivityType.Global);
		this.as.createNewActivity(userActivity);
		this.as.createNewActivity(friendActivity);
	}
}
